package storage

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"goDFS/etc"
	"goDFS/public"
	"goDFS/requests"
	ncf "goDFS/synchronization"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
)

//心跳包接口
func Heartbeat(c *gin.Context) {
	c.String(http.StatusOK, "1")
}

//上传文件逻辑
func UpLoad(c *gin.Context) {
	//进行token验证
	token := c.PostForm("token")
	if token == "" {
		etc.SaveLog("[ UpLoad ]  must have token", 2)
		c.JSON(http.StatusInternalServerError, public.NewJsonErrUse(0, "must have token"))
		return
	}

	tokenErr := public.DetectionToken(token, Conf.Tracker.Token)
	if tokenErr != nil {
		etc.SaveLog("[ Upload ]"+tokenErr.Error(), 3)
		c.JSON(http.StatusInternalServerError, public.NewJsonErrUse(0, tokenErr.Error()))
		return
	}

	file, err := c.FormFile("file")
	if err != nil {
		etc.SaveLog("[ Upload ]"+err.Error(), 3)
		c.JSON(http.StatusNotAcceptable, gin.H{"err": err.Error()})
		return
	}

	//打开文件
	f, err := file.Open()
	if err != nil {
		etc.SaveLog("[ Upload ]"+err.Error(), 3)
		c.JSON(http.StatusNotAcceptable, gin.H{"err": err.Error()})
		return
	}
	defer f.Close()

	//读取内容到fileByte
	buf := make([]byte, 1024)
	fileByte := make([]byte, 0, 1024)
	for {
		n, err := f.Read(buf)
		if err == io.EOF {
			break
		}
		fileByte = append(fileByte, buf[:n]...)

	}

	//生成令牌
	fileKey := NewFileKey(fileByte, file.Filename)

	//保存
	err = fileKey.SaveFile(fileByte, Conf)
	if err != nil {

		etc.SaveLog("[ Upload ]"+err.Error(), 3)
		c.JSON(http.StatusNotAcceptable, gin.H{"err": err.Error()})
		return
	}

	//保存完成，通过Tracker发起同步
	go ncf.SyncTracker(Conf, fileKey.Key, Address)

	c.JSON(http.StatusOK, gin.H{"key": fileKey.Key})

}

//文件下载逻辑
func GetFile(c *gin.Context) {
	key := c.DefaultQuery("key", "")
	if key == "" {
		etc.SaveLog("[ GetFile ]  not key", 3)
		c.JSON(http.StatusNotAcceptable, public.NewJsonErrUse(0, "not key"))
		return
	}

	fileKey, err := TokenToFileKey(key)
	if err != nil {
		etc.SaveLog("[ GetFile ]"+err.Error(), 3)
		c.JSON(http.StatusNotAcceptable, public.NewJsonErrUse(0, err.Error()))
		return
	}

	//打开文件
	buf, err := fileKey.ReadFile(Conf)
	if err != nil {
		etc.SaveLog("[ GetFile ]"+err.Error(), 3)
		c.JSON(http.StatusNotAcceptable, public.NewJsonErrUse(0, err.Error()))
		return
	}
	//返回结果
	dist := map[string]string{
		".html": "text/html",
		".txt":  "text/plain",
		".xml":  "text/xml",
		".gif":  "image/gif",
		".jpg":  "image/jpeg",
		".png":  " image/png",
		".json": "application/json",
		".pdf":  "application/pdf",
	}

	//判断文件类型

	val, ok := dist[strings.ToLower(fileKey.Extend)]
	if ok == false {
		val = "application/octet-stream"
	}

	//写入数据返回
	c.Writer.Header().Add("Content-Disposition",
		fmt.Sprintf("filename=%s%s", fileKey.Name, fileKey.Extend))
	c.Writer.Header().Add("Content-Type", val)
	c.Header("Accept-Length", fmt.Sprintf("%d", len(buf)))
	c.Writer.Write(buf)

	return

}

//文件同步
func ToSyncFile(c *gin.Context) {
	ip := c.DefaultQuery("ip", "")
	port := c.DefaultQuery("port", "")
	key := c.DefaultQuery("key", "")

	if ip == "" || port == "" || key == "" {
		etc.SaveLog("[ SyncFile ] key err", 3)
		c.JSON(http.StatusNotAcceptable, public.NewJsonErrUse(1, "key err"))
		return
	}

	//发起同步请求
	url := fmt.Sprintf("http://%s:%s%s", ip, port, GetApi)

	parms := map[string]string{
		"key": key,
	}

	url = requests.GetUrlBuild(url, parms)

	res, err := http.Get(url)
	if err != nil {
		etc.SaveLog("[ SyncFile ]"+err.Error(), 3)
		c.JSON(http.StatusInternalServerError, public.NewJsonErrUse(1, err.Error()))
		return
	}
	defer res.Body.Close()

	buf, err := ioutil.ReadAll(res.Body)
	if err != nil {
		etc.SaveLog("[ SyncFile ]"+err.Error(), 4)
		return
	}

	fileKey, err := TokenToFileKey(key)
	if err != nil {
		etc.SaveLog("[ SyncFile ]"+err.Error(), 3)
		c.JSON(http.StatusInternalServerError, public.NewJsonErrUse(1, err.Error()))
		return
	}

	err = fileKey.SaveFile(buf, Conf)
	if err != nil {
		etc.SaveLog("[ SyncFile ]"+err.Error(), 3)
		c.JSON(http.StatusInternalServerError, public.NewJsonErrUse(1, err.Error()))
		return
	}

	c.String(http.StatusOK, "1")

}
